from fastapi import FastAPI, Form
from contextlib import asynccontextmanager
from datetime import datetime, timedelta, time
import json
import os
import asyncio
import aiofiles  # 需要安装aiofiles库
import logging
from typing import Dict, Any, AsyncGenerator

# 配置日志 - 与FastAPI默认日志风格保持一致
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S"
)
logger = logging.getLogger("client_tracker")  # 定义专用日志器名称

# 访问日志去掉
uvicorn_access = logging.getLogger("uvicorn.access")
uvicorn_access.disabled = True

# 数据存储结构
# 格式: {id: {"lastUpdateTime": str, "onlineTime": int(分钟), "users": int}}
data_store: Dict[str, Dict[str, Any]] = {}

# 数据文件路径
DATA_FILE = "client_data.json"

def load_data():
    """从文件加载数据到内存（同步操作，仅启动时执行一次）"""
    global data_store
    if os.path.exists(DATA_FILE):
        try:
            with open(DATA_FILE, "r") as f:
                data_store = json.load(f)
            logger.info(f"已从{DATA_FILE}加载数据，共{len(data_store)}条记录")
        except Exception as e:
            logger.error(f"加载数据失败: {e}")

async def async_save_data():
    """异步保存数据到文件（使用aiofiles实现真正的异步文件操作）"""
    try:
        async with aiofiles.open(DATA_FILE, "w") as f:
            json_data = json.dumps(data_store, indent=2)
            await f.write(json_data)
        logger.info(f"数据已异步保存到{DATA_FILE}，共{len(data_store)}条记录")
    except Exception as e:
        logger.error(f"异步保存数据失败: {e}")

async def scheduled_saver():
    """定时保存数据的异步函数，每天凌晨4点33分执行"""
    while True:
        now = datetime.now()
        target_time = datetime.combine(now.date(), time(4, 33))
        if now > target_time:
            target_time += timedelta(days=1)
        
        wait_seconds = (target_time - now).total_seconds()
        logger.info(f"下次自动保存时间: {target_time}, 等待{wait_seconds:.2f}秒")
        
        await asyncio.sleep(wait_seconds)
        await async_save_data()

@asynccontextmanager
async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
    """生命周期事件处理"""
    # 启动操作
    load_data()
    saver_task = asyncio.create_task(scheduled_saver())
    logger.info("异步定时保存任务已启动")
    
    yield  # 应用运行期间
    
    # 关闭操作
    saver_task.cancel()
    try:
        await saver_task
    except asyncio.CancelledError:
        logger.info("定时保存任务已取消")
    
    logger.info("程序即将退出，正在保存数据...")
    await async_save_data()
    logger.info("数据保存完成，程序退出")

# 初始化FastAPI应用
app = FastAPI(lifespan=lifespan)

@app.post("/report/add")  # 接口路径修改为/report/add
async def receive_report(id: str = Form(...), user_count: int = Form(0), answer_count: int = Form(0)):
    """接收客户端发送的报告并更新数据"""
    current_time = datetime.now().isoformat()
    
    data = data_store.get(id, {'onlineTime': 0})
    data['onlineTime'] += 10
    data['lastUpdateTime'] = current_time
    data['users'] = user_count
    data['answers'] = answer_count
    data_store[id] = data
    
    return 1  # 简化返回数据为1

if __name__ == "__main__":
    import uvicorn
    # 单进程单线程运行
    uvicorn.run(
        "main:app",
        host="127.0.0.1",
        port=8000,
        workers=1,
        loop="asyncio",
        reload=False
    )
